home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / net_src.arc / ax_mbx.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-05-08  |  46.6 KB  |  1,825 lines

  1. /* Ok, I admit it... what I've done here is a mortal sin, but the XOBBS module
  2.    for ax_mbx.c is so different from the W9NK mailbox, and I hate forcing folks
  3.    to move files around before running a make, so here it is... the two cat'ed
  4.    together with an "if XOBBS ... else ... endif" wrapper... sick, but it
  5.    works...   Bdale */
  6.  
  7. #ifdef XOBBS
  8. /* XOBBS.C  module to link NET thru IPC message queues to the XOBBS mailbox. */
  9. /* Jim Durham, W2XO, 1-5-89 */
  10. /* requires a call to axchk() to be inserted in the main commutator loop of
  11.     the net main.c code */
  12.  
  13. #include <stdio.h>
  14. #include "global.h"
  15. #include "mbuf.h"
  16. #include "ax25.h"
  17. #include "timer.h"
  18. #include "lapb.h"
  19. #include "cmdparse.h"
  20. #include "iface.h"
  21. #include <fcntl.h>
  22. #include <signal.h>
  23. #include <sys/types.h>
  24. #include <sys/ipc.h>
  25. #include <sys/msg.h>
  26. #include "netrom.h"
  27. #include "nr4.h"
  28. #include "ax_mbx.h"
  29.  
  30. /*#define DEBUG       1*/
  31.  
  32. void fwdxmit();
  33. void fwdrecv();
  34. void fwdstate();
  35. void axbbs_xmit();
  36. void setfwd();
  37. char xogetc();
  38. static char conbuf[10][10];        /*buffers used in getco() and fwdcon()*/
  39. int conindex,conchar;
  40. int fwdflag;            /*flag to do various forwarding tasks*/
  41. int pid;
  42. int fwdbbsstate = NOCON;    /* con/discon state of forwarding bbs process */
  43. int smsgqid;            /* send-receive-control messsage que id's*/
  44. int rmsgqid;
  45. int scmsgqid;
  46. int rcmsgqid;
  47. int lastindex;                  /*last bbs index used*/
  48. int nsend;
  49. int ax25mbox;
  50. char temp[128];
  51. struct  ax25_cb *bbscb;        /*forwarding bbs control block*/
  52. struct message  msg;
  53.  
  54. struct mboxsess * base = NULLMBS;  /*pointer to base of mailbox chain*/
  55. struct mboxsess fwdstruct;    /*forwarding session*/
  56.  
  57. #ifdef SID2
  58. extern struct ax25_addr bbscall;
  59. #endif
  60.  
  61. static struct mboxsess *
  62. newmbox()
  63. {
  64.     struct mboxsess * mbp ;
  65.  
  66.         if(base == NULLMBS){
  67.             base =(struct mboxsess *)malloc(sizeof(struct mboxsess));
  68.             base->next = NULLMBS;
  69.         initmbox(base);
  70.             return base;
  71.         }
  72.         else{
  73.         mbp = base;
  74.         while(mbp->next != NULLMBS)       /*go up the chain to the top*/
  75.             mbp = mbp->next;
  76.         mbp->next =(struct mboxsess *)malloc(sizeof(struct mboxsess));
  77.         mbp->next->next = NULLMBS;
  78.         initmbox(mbp->next);
  79.         return mbp->next;
  80.     }
  81. }
  82.  
  83. initmbox(mbp)
  84.     struct mboxsess * mbp;
  85. {
  86.     
  87.     mbp->bytes = 0;
  88.     mbp->gotbytes = 0;
  89.     mbp->mtxtptr = mbp->rmsgbuf.mtext;
  90. }
  91.  
  92. freembox(mbp)
  93.     struct mboxsess * mbp;
  94. {
  95.     struct mboxsess *p;
  96.     
  97.     if(mbp == base){            /*special case for base session*/
  98.         if(base->next != NULLMBS)/*if base is NOT the only session*/
  99.             base = base->next;   /*then make base point to next session*/
  100.         else
  101.             base = NULLMBS;     /*otherwise,just set base to NULLMBS*/
  102.         free(mbp);              /*free up the storage*/
  103.         return;                 /*and go away*/
  104.     }
  105.     p = base;
  106.     for(;;){
  107.         if(p->next == mbp){     /*if the next upward session is THE one*/
  108.             p->next = mbp->next; /*eliminate the next upward session*/
  109.             free(mbp);
  110.             return;
  111.         }
  112.         if(p->next == NULLMBS){ /*something is wrong here!*/
  113.             free(mbp);          /*try to fix it*/
  114.             return;
  115.         }
  116.         p = p->next;
  117.     }
  118. }
  119.     
  120.             
  121. axchk()        /* service any ax25 connections w2xo 9-1-88*/
  122. {
  123.     int rdcnt;
  124.     struct mbuf *bp;
  125.     struct mboxsess * mbp;
  126.     char *cp;
  127.     int testsize,size;
  128.     void axinit();
  129.     
  130. /* initialization code removed.  call to axinit() direct from main now. */
  131.     
  132.     if(base == NULLMBS)                       /*no mailboxes?..then leave*/
  133.         goto fcontchk;
  134.     mbp = base;                    /*point to the session base*/
  135.     while(mbp != NULLMBS){            /*and climb the session links*/
  136.         if(mbp->gotbytes < 1)            /*if we need input*/
  137.             if((mbp->gotbytes=msgrcv(smsgqid,&mbp->rmsgbuf,1024,(long)mbp->pid,
  138.                IPC_NOWAIT|0600)) < 1)        /*and there is none, ..punt*/
  139.                  goto contchk;
  140.             else                /*got input!*/
  141.                 mbp->mtxtptr = mbp->rmsgbuf.mtext; /*new message buffer, set to start*/
  142.  
  143.             testsize = min(mbp->bytes,mbp->cbadr.axbbscb->paclen+1);      /* get the minimum of the # */
  144.             size = min(testsize, mbp->gotbytes) + 1;       /* of bytes avail and paclen*/
  145.             bp = alloc_mbuf(size);                  /* then min of avail and have*/
  146.             cp = bp->data;
  147.         if(mbp->proto == AX25){
  148.                 *cp++ = PID_FIRST | PID_LAST | PID_NO_L3;
  149.                 bp->cnt =1;
  150.             }
  151.             else  bp->cnt = 0;
  152.             
  153.             while(bp->cnt < size && mbp->gotbytes){
  154.                 *cp++ = *mbp->mtxtptr++;
  155.                 bp->cnt++;
  156.                 mbp->gotbytes--;
  157.             }
  158.  
  159.         if(mbp->proto == AX25)
  160.             send_ax25(mbp->cbadr.axbbscb,bp);
  161.         else
  162.             send_nr4(mbp->cbadr.axnrcb,bp);
  163.                 /*now, check for control messages*/
  164.  
  165. contchk:    rdcnt=msgrcv(scmsgqid,&msg,1024,(long)mbp->pid,IPC_NOWAIT|0600);
  166. #ifdef DEBUG
  167.         if(rdcnt > 0) printf("net:Control Message received: rdcnt=%d\n",rdcnt);
  168. #endif
  169.             switch(rdcnt){
  170.                 case 0:     break;
  171.                 case -1:    /*perror("axchk002");*/
  172.                             break;
  173.                 default:    if(msg.mtext[0] == 'K'){
  174. #ifdef DEBUG
  175.                     printf("recbbs: K received\n");
  176. #endif
  177.                 kill(mbp->pid,9);
  178.                 wait(NULLCHAR);
  179.                 clearque(mbp->pid);
  180.                  if(mbp->proto == AX25)
  181.                      disc_ax25(mbp->cbadr.axbbscb);
  182.                  else
  183.                      disc_nr4(mbp->cbadr.axnrcb);
  184.  
  185.                 freembox(mbp);
  186.                             }/* if K */
  187.             }/* switch */
  188.         mbp = mbp->next;
  189.     }/*while loop*/
  190.  
  191. fcontchk:    chkfwd();            /*check the forwarder*/
  192. }
  193.  
  194. dombox(argc, argv)
  195. int argc ;
  196. char *argv[] ;
  197. {
  198.     if (argc < 2) {
  199.         domboxdisplay() ;
  200.         return 0 ;
  201.     }
  202.  
  203.     if (argv[1][0] == 'y' || (strcmp(argv[1],"on") == 0))
  204.         ax25mbox = 1 ;
  205.     else if (argv[1][0] == 'n' || (strcmp(argv[1],"off") == 0))
  206.         ax25mbox = 0 ;
  207.     else if (argv[1][0] == '?')
  208.         printf("ax25 mailbox is %s\n", ax25mbox ? "on" : "off") ;
  209.     else
  210.         printf("usage: mbox [y|n|?]\n") ;
  211.  
  212.     return 0 ;
  213. }
  214.  
  215. static domboxdisplay()
  216. {
  217.  
  218.     struct mboxsess * mbp;
  219.     printf("Process-ID     &cb      Protocol      User\n") ;
  220.         mbp = base;    
  221.     while(mbp != NULLMBS){
  222.             printf("%-13d%-13x",mbp->pid,mbp->cbadr.axbbscb);             
  223.                 if(mbp->proto == AX25)
  224.                 printf("Ax25        %s\n",mbp->call);
  225.             else
  226.                 printf("Net/Rom     %s\n",mbp->call);
  227.             mbp = mbp->next;
  228.         }/*while loop*/
  229.     printf("\n\n");
  230. }
  231. /* Incoming mailbox session via ax.25 */
  232.  
  233.  
  234. /* * This is the ax25 receive upcall function
  235.  *it gathers incoming data and stuff it down the IPC queue to the proper BBS
  236.  */
  237.  
  238. void
  239. mbx_incom(axp,cnt)    
  240. struct ax25_cb *axp;
  241. int16 cnt;
  242. {
  243. #ifndef SID2
  244.         char arg1[10],arg2[10],arg3[10],arg4[10],arg5[10];    
  245.     void mbx_tx(), mbx_rx(), mbx_state();
  246.     int j;
  247.     struct mboxsess *mbp;
  248.     struct mbuf *bp;
  249.     struct mbuf *recv_ax25();
  250.     
  251.                 mbp =newmbox();        /*after this, this is a mailbox connection*/
  252.                         /* so, make a new mailbox session*/
  253.             axp->r_upcall = mbx_rx ;
  254.             axp->t_upcall = mbx_tx ;
  255.         axp->s_upcall = mbx_state;
  256.                 mbp->cbadr.axbbscb=axp;
  257.                 mbp->proto = AX25;
  258.                 mbp->bytes = 32;    /*jump start the upcall*/
  259.  
  260.         bp = recv_ax25(axp,cnt) ;    /* get the initial input */
  261.         free_p(bp) ;            /* and throw it away to avoid confusion */
  262.  
  263.  
  264.                 for(j=0;j<6;j++){               /*now, get incoming call letters*/
  265.                     arg1[j]=mbp->cbadr.axbbscb->addr.dest.call[j];
  266.                     arg1[j]=arg1[j] >> 1;
  267.                     arg1[j]=arg1[j] & (char)0x7f;
  268.                     if(arg1[j]==' ') arg1[j]='\0';
  269.                 }
  270.                 arg1[6]='\0';            /*terminate call letters*/
  271.             strcpy(mbp->call,arg1);   /*Copy call to session*/
  272.                 sprintf(arg2,"%d\0",rmsgqid);   /*set up args telling what the*/
  273.                 sprintf(arg3,"%d\0",smsgqid);   /*message ques are for the */
  274.                 sprintf(arg4,"%d\0",rcmsgqid);   /*execed process*/
  275.                 sprintf(arg5,"%d\0",scmsgqid);   /*execed process*/
  276.  
  277.                                            /*now, fork and exec the bbs*/
  278.                 if((pid=fork()) == 0){              /*if we are the child*/
  279.                     if(execl("/u/newbbs/xobbs","xobbs",arg1,arg2,arg3,arg4,arg5,0) < 0){
  280. #ifdef DEBUG
  281.                         printf("Bad exec on BBS\n");
  282. #endif
  283.                         exit(1);
  284.                     }
  285.                 }
  286.                 else                      /* parent process is still NET */
  287.                     mbp->pid=pid;         /* save pid of new baby*/
  288. #endif
  289. }    
  290.  
  291. void
  292. mbx_rx(axp,cnt)        /*w2xo  2-16-89  */
  293. struct ax25_cb *axp;        /* send chars down pipe to bbs */
  294. int16 cnt;
  295. {
  296.     struct mbuf *bp;
  297.     struct mbuf *recv_ax25();
  298.     struct mboxsess * mbp;
  299.  
  300.     
  301.     if(base == NULLMBS)
  302.         return;
  303.     mbp = base;
  304.     while(mbp != NULLMBS){
  305.     if(mbp->proto == AX25){
  306.             if(mbp->cbadr.axbbscb == axp){  /* match requested block? */
  307.                 if((bp = recv_ax25(axp,cnt)) == NULLBUF)  /*nothing there*/
  308.             continue;
  309.                 while(bp != NULLBUF){
  310.                     strncpy(msg.mtext,bp->data,bp->cnt);
  311.                     msg.mtype = (long)mbp->pid;
  312.                     if(msgsnd(rmsgqid,&msg,bp->cnt,IPC_NOWAIT|0600) < 0)
  313.                         perror("axincoming");
  314.                     bp=free_mbuf(bp);   /*free the mbuf and get the next */
  315.                 }
  316.             } /* if matching axp */
  317.         }/*if ax25 */
  318.     mbp = mbp->next;
  319.     }/*while loop*/
  320. }
  321.  
  322. void
  323. mbx_tx(axp,cnt)
  324. struct ax25_cb *axp;
  325. int16 cnt;
  326. {
  327.     struct mboxsess * mbp;
  328.     if(base == NULLMBS)
  329.         return;                     /*no sessions*/
  330.     mbp = base;
  331.     while(mbp != NULLMBS){
  332.         if(mbp->cbadr.axbbscb == axp)
  333.             mbp->bytes = cnt;
  334.     mbp = mbp->next;
  335.     }
  336. }
  337.  
  338. void
  339. mbx_state(axp,old,new)        /*w2xo  3-23-89 */
  340. struct ax25_cb *axp;
  341. int old,new;
  342. {
  343. #ifdef SID2
  344.         char arg1[10],arg2[10],arg3[10],arg4[10],arg5[10];    
  345.     void mbx_tx(), mbx_rx(), mbx_state();
  346.     int j;
  347. #endif
  348.     struct mboxsess *mbp;
  349.  
  350.         switch(new){
  351.             case DISCONNECTED:
  352.            if((old == DISCONNECTED) || (old == DISCPENDING))
  353.                return;
  354.                 if(base == NULLMBS)
  355.                     break;
  356.             mbp = base;
  357.                 while(mbp != NULLMBS){
  358.                     if(axp == mbp->cbadr.axbbscb && mbp->proto == AX25){
  359.                         kill(mbp->pid,9);     /*kill bbs process*/
  360.                         wait(NULLCHAR);
  361.                         freembox(mbp);
  362.                         break; /* from while loop */
  363.                     } /*if*/
  364.                     mbp = mbp->next;
  365.                 }/*while loop*/
  366.                 break;   /*end of DISCONNECTED case*/
  367.                     
  368.             case CONNECTED:
  369. #ifdef SID2
  370.         if(old != DISCONNECTED)
  371.             return;
  372.             if(!calleq(axp,&bbscall)){ /*not for the mailbox*/
  373.             axp->s_upcall = NULLVFP;
  374.             return;
  375.             }
  376.     
  377.                 mbp =newmbox();        /*after this, this is a mailbox connection*/
  378.                         /* so, make a new mailbox session*/
  379.             axp->r_upcall = mbx_rx ;
  380.             axp->t_upcall = mbx_tx ;
  381.  
  382.                 mbp->cbadr.axbbscb=axp;
  383.                 mbp->proto = AX25;
  384.                 mbp->bytes = 32;    /*jump start the upcall*/
  385.  
  386.                 for(j=0;j<6;j++){               /*now, get incoming call letters*/
  387.                     arg1[j]=mbp->cbadr.axbbscb->addr.dest.call[j];
  388.                     arg1[j]=arg1[j] >> 1;
  389.                     arg1[j]=arg1[j] & (char)0x7f;
  390.                     if(arg1[j]==' ') arg1[j]='\0';
  391.                 }
  392.                 arg1[6]='\0';            /*terminate call letters*/
  393.             strcpy(mbp->call,arg1);   /*Copy call to session*/
  394.                 sprintf(arg2,"%d\0",rmsgqid);   /*set up args telling what the*/
  395.                 sprintf(arg3,"%d\0",smsgqid);   /*message ques are for the */
  396.                 sprintf(arg4,"%d\0",rcmsgqid);   /*execed process*/
  397.                 sprintf(arg5,"%d\0",scmsgqid);   /*execed process*/
  398.  
  399.                                            /*now, fork and exec the bbs*/
  400.                 if((pid=fork()) == 0){              /*if we are the child*/
  401.                     if(execl("/u/newbbs/xobbs","xobbs",arg1,arg2,arg3,arg4,arg5,0) < 0){
  402. #ifdef DEBUG
  403.                         printf("Bad exec on BBS\n");
  404. #endif
  405.                         exit(1);
  406.                     }
  407.                 }
  408.                 else                      /* parent process is still NET */
  409.                     mbp->pid=pid;         /* save pid of new baby*/
  410. #endif
  411.                 break;
  412.         }/* end of switch*/
  413. }/*end of routine*/
  414.  
  415.  
  416. /* Incoming mailbox session via net/rom */
  417.  
  418. void
  419. mbx_nr4incom(cb)
  420. register struct nr4cb *cb ;
  421. {
  422.     void mbx_nr4tx(), mbx_nr4rx(), mbx_nr4state() ;
  423.         char arg1[10],arg2[10],arg3[10],arg4[10],arg5[10];
  424.         struct mboxsess * mbp;
  425.     int j;
  426.         
  427.         mbp = newmbox();
  428.  
  429.     cb->r_upcall = mbx_nr4rx ;
  430.     cb->s_upcall = mbx_nr4state ;
  431.     cb->t_upcall = mbx_nr4tx ;
  432.  
  433.         mbp->cbadr.axnrcb = cb;
  434.         mbp->proto = NTRM;
  435.         mbp->bytes = 32;    /*jump start the upcall*/
  436.  
  437.         for(j=0;j<6;j++){               /*now, get incoming call letters*/
  438.             arg1[j]=mbp->cbadr.axnrcb->user.call[j];
  439.             arg1[j]=arg1[j] >> 1;
  440.             arg1[j]=arg1[j] & (char)0x7f;
  441.             if(arg1[j]==' ') arg1[j]='\0';
  442.         }
  443.         arg1[6]='\0';            /*terminate call letters*/
  444.     strcpy(mbp->call,arg1);  /*copy call to session*/
  445.  
  446.         sprintf(arg2,"%d\0",rmsgqid);   /*set up args telling what the*/
  447.         sprintf(arg3,"%d\0",smsgqid);   /*message ques are for the */
  448.         sprintf(arg4,"%d\0",rcmsgqid);   /*execed process*/
  449.         sprintf(arg5,"%d\0",scmsgqid);   /*execed process*/
  450.  
  451.                                          /*now, fork and exec the bbs*/
  452.         if((pid=fork()) == 0){              /*if we are the child*/
  453.             if(execl("/u/newbbs/xobbs","xobbs",arg1,arg2,arg3,arg4,arg5,0) < 0){
  454. #ifdef DEBUG
  455.                 printf("Bad exec on BBS\n");
  456. #endif
  457.                 exit(1);
  458.             }
  459.         }
  460.         else                            /* parent process is still NET */
  461.             mbp->pid=pid;         /* save pid of new baby*/
  462. }
  463.  
  464. /* receive upcall for net/rom */
  465. /* mbx_nr4rx collects lines, and calls mbx_line when they are complete. */
  466. /* If the lines get too long, it arbitrarily breaks them. */
  467.  
  468. void mbx_nr4rx(cb,cnt)
  469. struct nr4cb *cb ;
  470. int16 cnt ;
  471. {
  472.     struct mbuf *bp;
  473.     struct mbuf *recv_ax25();
  474.     struct mboxsess * mbp;
  475.  
  476.  
  477.     
  478.     if(base == NULLMBS)
  479.         return;
  480.     mbp = base;
  481.     while(mbp != NULLMBS){
  482.     if(mbp->proto == NTRM){
  483.             if(mbp->cbadr.axnrcb == cb){  /* match requested block? */
  484.                 if((bp = recv_nr4(cb,cnt)) == NULLBUF)  /*nothing there*/
  485.             continue;
  486.                 while(bp != NULLBUF){
  487.                     strncpy(msg.mtext,bp->data,bp->cnt);
  488.                     msg.mtype = (long)mbp->pid;
  489.                     if(msgsnd(rmsgqid,&msg,bp->cnt,IPC_NOWAIT|0600) < 0)
  490.                         perror("nrincoming");
  491.                     bp=free_mbuf(bp);   /*free the mbuf and get the next */
  492.                 }
  493.             } /* if matching axp */
  494.         } /* if netrom */
  495.     mbp = mbp->next;
  496.     } /*while loop*/
  497. }
  498.  
  499. void
  500. mbx_nr4tx(cb,cnt)
  501. struct nr4cb *cb;
  502. int16 cnt;
  503. {
  504.     struct mboxsess *mbp;
  505.     if(base == NULLMBS)
  506.         return;
  507.     mbp = base;
  508.     while(mbp != NULLMBS){
  509.         if(mbp->cbadr.axnrcb == cb)
  510.             mbp->bytes = cnt;
  511.         mbp = mbp->next;
  512.     }
  513. }
  514.  
  515. /* state upcall for net/rom */
  516. void mbx_nr4state(cb,old,new)
  517. struct nr4cb *cb ;
  518. int old, new ;
  519. {
  520.     struct mboxsess * mbp;
  521.  
  522.     switch(new){
  523.         case DISCONNECTED:
  524.             if(base == NULLMBS)
  525.                 return;
  526.             mbp = base;
  527.             while(mbp != NULLMBS){
  528.                 if(cb == mbp->cbadr.axnrcb){
  529.                     kill(mbp->pid,9);     /*kill bbs process*/
  530.                     wait(NULLCHAR);
  531.                     freembox(mbp);
  532.                     break; /* from for loop */
  533.                 }
  534.             mbp = mbp->next;
  535.             }/*end of while loop*/
  536.         break;   /*end of DISCONNECTED case*/
  537.                     
  538.         case CONNECTED:
  539.             break; /* end of connected case*/
  540.     }/* end of switch*/
  541. }/*end of routine*/
  542.  
  543. indexx(s,t)
  544. char s[],t[];
  545. {
  546.     int i,j,k;
  547.     
  548.     for(i=0;s[i]!= '\0'; i++){
  549.         for(j=i,k=0;t[k]!='\0' && s[j] == t[k]; j++,k++)
  550.             ;
  551.         if(t[k] == '\0')
  552.             return(i);
  553.     }
  554.     return(-1);
  555. }
  556.  
  557.  
  558. chkfwd()                /* check forwarding and take appropriate*/
  559. {                    /* actions*/
  560.     int gotbytes;
  561.     if(fwdbbsstate==WAIT)
  562.         return;
  563.     switch(fwdflag){
  564.         case NOFWD:     break;
  565.         case SPAWNBBS:  spawnfwd();
  566.                         nsend = false;
  567.                         break;
  568.         case DOCONNECT: fwdcon();
  569.                         break;
  570.         case READXMIT : fwdsend();
  571.                         break;
  572.         case GETCON:    getcon();
  573.                         break;
  574.         case CLEARCON:  clearcon(nsend);
  575.                 if(!(nsend))    /* only do clearcon without N once*/
  576.                     nsend = true;
  577.                         break;
  578.         case WAITING:   break;
  579.         default: break;
  580.     }
  581.     if(fwdstruct.cbadr.axbbscb != NULLFWD){ /*if forwarder, check for control*/
  582.         gotbytes = msgrcv(scmsgqid,&msg,256,(long)fwdstruct.pid,IPC_NOWAIT|0600);
  583.         switch(gotbytes){
  584.             case 0:     break;
  585.             case -1:    /*perror("axchk003");*/
  586.                         break;
  587.             default:    if(msg.mtext[0] == 'K'){
  588.                         kill(fwdstruct.pid,9);
  589.                         wait(NULLCHAR);
  590. #ifdef DEBUG
  591.             printf("clearing ques\n");
  592. #endif
  593.                         clearque(fwdstruct.pid);
  594.             disc_ax25(fwdstruct.cbadr.axbbscb);
  595.                     fwdstruct.cbadr.axbbscb = NULLFWD;
  596.                         }
  597.                         else if(msg.mtext[0] == 'N'){
  598. #ifdef DEBUG
  599.                             printf("net:N received from BBS\n");
  600. #endif
  601.                             if(fwdbbsstate==YESCON){ /*if we are really connected*/
  602.                                 fwdbbsstate=WAIT;  /*wait until disconnect before next*/
  603.                                 disc_ax25(fwdstruct.cbadr.axbbscb); /*do the disconnect */
  604. #ifdef DEBUG
  605.                             printf("net:disconnect issued\n");
  606. #endif
  607.                             }
  608. #ifdef DEBUG
  609.                             printf("net:setting flag to CLEARCON\n");
  610. #endif
  611.                             fwdflag=CLEARCON;  /*set up for next connect*/
  612.                         }
  613.                         break;
  614.         } /*switch*/
  615.     } /* if forwarder active */
  616. }
  617.  
  618. spawnfwd()
  619. {
  620.     char arg1[20],arg2[20],arg3[20],arg4[20],arg5[20];
  621.  
  622.                   /*fork and exec the forwarder*/
  623.     if((fwdstruct.pid=fork()) == 0){              /* if this is the child*/
  624.         strcpy(arg1,"forward");
  625.         sprintf(arg2,"%d\0",rmsgqid);    /*tell the bbs what the message*/
  626.         sprintf(arg3,"%d\0",smsgqid);     /* que ids to use are*/
  627.         sprintf(arg4,"%d\0",rcmsgqid);
  628.         sprintf(arg5,"%d\0",scmsgqid);
  629.  
  630.             /*check for bad exec */
  631.         if(execl("/u/newbbs/xobbs","xobbs",arg1,arg2,arg3,arg4,arg5,0) < 0){
  632.         fprintf(stderr,"Bad Exec on forwarder\n");
  633.         exit(1);
  634.     }
  635.     }/* if fwdstruct.pid is 0 */
  636.     else{
  637.         fwdflag=CLEARCON;  /*not the child, so set flag for next level*/
  638.     fwdstruct.gotbytes = 0;
  639.     fwdstruct.bytes = 0;
  640.     fwdstruct.proto = AX25;
  641.     fwdstruct.mtxtptr = fwdstruct.rmsgbuf.mtext;
  642.     }
  643. }
  644.     
  645. clearcon(nsend)
  646.     int nsend;
  647. {
  648.     int i;
  649.  
  650. #ifdef DEBUG
  651.     printf("net:clearcon:entering routine\n");
  652. #endif
  653.     for(i=0;i<10;i++)
  654.         conbuf[i][0]='\0';
  655. #ifdef DEBUG
  656.     printf("net:clearcon:Clearing ques\n");
  657. #endif
  658.     conindex=conchar=0;            /*clear the connect buffer*/
  659.     fwdflag=GETCON;
  660.     clearque(fwdstruct.pid);
  661.     if(nsend && fwdstruct.cbadr.axbbscb != NULLFWD){  /*don't send N to new bbs or no bbs */
  662.         msg.mtype = (long)fwdstruct.pid;
  663.     sprintf(msg.mtext,"N\0");
  664. #ifdef DEBUG
  665.         printf("net:Sending %s to bbs\n",msg.mtext);
  666. #endif
  667.         msgsnd(rcmsgqid,&msg,2,IPC_NOWAIT|0600);
  668. #ifdef DEBUG
  669.         printf("net:clearcon:sent N to bbs process ID %d\n",fwdstruct.pid);
  670. #endif
  671.     }
  672. }
  673.     
  674.  
  675. getcon()                        /*routine called when fwdflag is "GETCON"*/
  676. {                               /* to read the connect request*/
  677.  
  678.     fwdstruct.gotbytes = msgrcv(smsgqid,&fwdstruct.rmsgbuf,256,(long)fwdstruct.pid,IPC_NOWAIT|0600);  /* is there anything in the pipe?*/
  679.     switch(fwdstruct.gotbytes){
  680.         case 0:     return;
  681.         case -1:    /*perror("getcon001");*/
  682.                     break;
  683.         default:    strncpy(conbuf[conindex],fwdstruct.rmsgbuf.mtext,fwdstruct.gotbytes);
  684.             if(fwdstruct.rmsgbuf.mtext[0] != 0x04){
  685.                         conbuf[conindex++][fwdstruct.gotbytes] = '\0';
  686.                         break;
  687.                    }
  688.                    else
  689.                    fwdflag = DOCONNECT;
  690.     }
  691.     fwdstruct.gotbytes=0;
  692. }
  693.  
  694. fwdcon()
  695. {
  696.     char *argv[10];
  697.  
  698.     char buf[128];
  699.     static char temp[] = "con";
  700.  
  701.     int numdigis;
  702.     int i;
  703.       
  704.     argv[1] = &conbuf[0][0];    /* get device to use*/
  705.     argv[2] = &conbuf[1][0];    /* get who to connect to*/
  706.     numdigis=atoi(&conbuf[2][0]);
  707.     for(i=0; i < numdigis;i++)
  708.         argv[3+i] = &conbuf[2+i][0];
  709.  
  710.     argv[0]= temp;              /* set up for the doconfwd() call */
  711.  
  712.     fflush(stdout);
  713.      if(!doconfwd(3+numdigis,argv)){               /*do the connect*/
  714.          sprintf(msg.mtext,"OK\n");
  715.          msg.mtype = (long)fwdstruct.pid;
  716.          if(msgsnd(rmsgqid,&msg,3,IPC_NOWAIT|0600) < 0)
  717.              perror("fwdcon001");
  718.      fwdflag=WAITING;
  719.          return 0;
  720.      }
  721.      else{
  722.          sprintf(buf,"NOGOOD\n");
  723.      msg.mtype = (long)fwdstruct.pid;
  724.          if(msgsnd(rmsgqid,&msg,7,IPC_NOWAIT|0600) < 0)
  725.              perror("fwdcon002");
  726.          fwdflag=CLEARCON;
  727.          return 1;
  728.     }
  729. }
  730.  
  731. void
  732. fwdstate(axp,old,new)        /*w2xo      10-24-88 */
  733. struct ax25_cb *axp;
  734. int old,new;
  735. {
  736.  
  737.  
  738.     switch(new){
  739.     case DISCONNECTED:  if(fwdflag==READXMIT){
  740.                 fwdflag=CLEARCON;
  741.                 }
  742.                 fwdbbsstate=NOCON;
  743.                 kill(fwdstruct.pid,SIGUSR1); /*tell bbs about discon*/
  744.                 break;
  745.                             
  746.     case CONNECTED:        fwdflag=READXMIT;
  747.                 fwdstruct.bytes = 32; /*jump start t_upcall*/
  748.                 fwdbbsstate=YESCON;
  749.                 break;
  750.         default:            break;
  751.     }
  752. }
  753.  
  754. void
  755. fwdxmit(axp,cnt)
  756. struct ax25_cb *axp;
  757. int16 cnt;
  758. {
  759.         /*all we want to do here is establish the max number of*/
  760.         /* bytes to send at any one time*/
  761.  
  762.     if(axp == fwdstruct.cbadr.axbbscb)
  763.         fwdstruct.bytes = cnt;
  764. }
  765.  
  766. void
  767. fwdrecv(axp,cnt)        /*w2xo  10-24-88  */
  768. struct ax25_cb *axp;        /* send chars down pipe to forwarding bbs */
  769. int16 cnt;
  770. {
  771.     struct mbuf *bp;
  772.     struct mbuf *recv_ax25();
  773.     
  774.     if((bp = recv_ax25(axp,cnt)) == NULLBUF)  /*nothing there*/
  775.         return;
  776.  
  777.     while(bp != NULLBUF){
  778.         strncpy(msg.mtext,bp->data,bp->cnt);
  779.     msg.mtype = (long)fwdstruct.pid;
  780.         if(msgsnd(rmsgqid,&msg,bp->cnt,IPC_NOWAIT|0600) < 0)
  781.             perror("fwdrecv");
  782.         bp=free_mbuf(bp);
  783.     }
  784. }
  785.  
  786. fwdsend()        /* service bbs ax25 connections w2xo 10-24-88*/
  787. {
  788.     int size,testsize;
  789.     struct mbuf *bp;
  790.     char *cp;
  791.  
  792.     if(fwdstruct.cbadr.axbbscb != NULLFWD){
  793.         if(fwdstruct.gotbytes < 1)
  794.             if((fwdstruct.gotbytes=msgrcv(smsgqid,&fwdstruct.rmsgbuf,256,(long)fwdstruct.pid,
  795.                IPC_NOWAIT|0600)) < 1)
  796.                  return;   /*return if nothing to send*/
  797.             else
  798.                 fwdstruct.mtxtptr = fwdstruct.rmsgbuf.mtext; /*new message buffer, set to start*/
  799.  
  800.         testsize = min(fwdstruct.bytes,fwdstruct.cbadr.axbbscb->paclen+1);      /* get the minimum of the # */
  801.         size = min(testsize, fwdstruct.gotbytes) +1;       /* of bytes avail and paclen*/
  802.         bp = alloc_mbuf(size);                  /* then min of avail and have*/
  803.         cp = bp->data;
  804.         *cp++ = PID_FIRST | PID_LAST | PID_NO_L3;
  805.         bp->cnt = 1;
  806.         while(bp->cnt < size){
  807.             *cp++ = *fwdstruct.mtxtptr++;
  808.             bp->cnt++;
  809.             fwdstruct.gotbytes--;
  810.         }
  811.         send_ax25(fwdstruct.cbadr.axbbscb,bp);
  812.     } /*if active */
  813. }
  814.  
  815. /* Initiate AX.25 forwarding connection to remote bbs */
  816. doconfwd(argc,argv)
  817. int argc;
  818. char **argv;
  819.  {
  820.     void fwdrecv(),fwdxmit(),fwdstate();
  821.     struct ax25_addr dest;
  822.     struct ax25 addr;
  823.     struct ax25_cb *open_ax25();
  824.     struct interface *ifp;
  825.     struct mboxsess *mbp;
  826.     extern int16 axwindow;
  827.     int i;
  828.  
  829.     for(ifp = ifaces; ifp != NULLIF; ifp = ifp->next)
  830.         if(strcmp(argv[1],ifp->name) == 0)
  831.             break;
  832.     if(ifp == NULLIF){
  833.         printf("Interface %s unknown\n",argv[1]);
  834.         return 1;
  835.     }
  836.  
  837.     mbp = base;            /* point to the session base */
  838.     while (mbp != NULLMBS) {    /* and climb the session */
  839.         if (!strncmp(mbp->call,argv[2],strlen(mbp->call)))
  840.             return 1;
  841.         mbp = mbp->next;    /* bomb out if session to this bbs */
  842.     }                /* exists */
  843.  
  844.     setcall(&dest,argv[2]);
  845. #ifndef NETROM
  846.     ASSIGN(addr.source,mycall);
  847. #else
  848.     memcpy(&addr.source,ifp->hwaddr,AXALEN);
  849. #endif
  850.     setcall(&addr.dest,argv[2]);
  851.     for(i=3; i < argc; i++)
  852.         setcall(&addr.digis[i-3],argv[i]);
  853.  
  854.     addr.ndigis = i - 3;
  855.     fwdstruct.cbadr.axbbscb = open_ax25(&addr,axwindow,fwdrecv,fwdxmit,fwdstate,ifp,(char *)0);
  856.     return 0;
  857. }
  858.  
  859.  
  860. fgetline(fd,s)
  861.     int fd;
  862.     char *s;
  863. {
  864.     int i;
  865.     char c;
  866.     i=0;
  867.     while((c=xogetc(fd)) && ((c != '\n') && (c != '\r')))
  868.         s[i++] = c;
  869.  
  870.     s[i] = '\0';
  871.     return(i);
  872. }
  873.  
  874.  
  875. char xogetc(fd)
  876. {
  877.     char c;
  878.     if(read(fd,&c,1)){
  879.         c &= (char)0x7f;        /*strip 8th bit and up*/
  880.         if(c=='\r')
  881.             c='\n';
  882.         return(c);
  883.     }
  884.     else return('\0');
  885. }
  886.  
  887.  
  888. void
  889. setfwd(){
  890.     fwdflag=SPAWNBBS;
  891.     signal(SIGUSR2,setfwd);
  892. }
  893.  
  894. void
  895. axinit()
  896. {
  897.         signal(SIGUSR2,setfwd);  /* set signal 17 to initiate forwarding*/
  898.     if((smsgqid=msgget(200,IPC_CREAT|0600)) < 0){
  899.         perror("msgget smsgqid:");
  900.         exit(1);
  901.     }
  902.     else
  903.         printf("\tPBBS Send message que identifier is:%d\n",smsgqid);
  904.         
  905.     if((rmsgqid=msgget(201,IPC_CREAT|0600)) < 0){
  906.         perror("msgget rmsgqid:");
  907.         exit(1);
  908.     }
  909.     else
  910.         printf("\tPBBS Receive message que identifier is:%d\n",rmsgqid);
  911.  
  912.     if((scmsgqid=msgget(202,IPC_CREAT|0600)) < 0){
  913.         perror("msgget scmsgqid:");
  914.         exit(1);
  915.     }
  916.     else
  917.         printf("\tPBBS Control send message que identifier is:%d\n",scmsgqid);
  918.  
  919.     if((rcmsgqid=msgget(203,IPC_CREAT|0600)) < 0){
  920.         perror("msgget rcmsgqid:");
  921.         exit(1);
  922.     }
  923.     else
  924.         printf("\tPBBS Control receive message que identifier is:%d\n",rcmsgqid);
  925.  
  926. }
  927.  
  928. clearque(pid)
  929.     int pid;
  930. {
  931.     while(msgrcv(smsgqid,&msg,256,(long)pid,IPC_NOWAIT|0600) > 0)
  932.         ;
  933.     while(msgrcv(rmsgqid,&msg,256,(long)pid,IPC_NOWAIT|0600) > 0)
  934.         ;
  935.     while(msgrcv(scmsgqid,&msg,256,(long)pid,IPC_NOWAIT|0600) > 0)
  936.         ;
  937.     while(msgrcv(rcmsgqid,&msg,256,(long)pid,IPC_NOWAIT|0600) > 0)
  938.         ;
  939. }
  940.  
  941. calleq(axp,addr)
  942.     struct ax25_cb *axp;
  943.     struct ax25_addr *addr;
  944. {
  945.     register int i;
  946.  
  947.     if(memcmp(axp->addr.source.call,addr->call,ALEN) != 0)
  948.         return 0;
  949.     if((axp->addr.source.ssid & SSID) != (addr->ssid & SSID))
  950.         return 0;
  951.     return 1;
  952. }
  953.  
  954. #else /* not XOBBS */
  955.  
  956. #include <stdio.h>
  957. #include <time.h>
  958. #include <ctype.h>
  959. #ifdef    UNIX
  960. #include <sys/types.h>
  961. #endif
  962. #include "global.h"
  963. #include "mbuf.h"
  964. #include "ax25.h"
  965. #include "timer.h"
  966. #include "iface.h"
  967. #include "lapb.h"
  968. #include "netrom.h"
  969. #include "nr4.h"
  970. #include "ax_mbx.h"
  971. #include "cmdparse.h"
  972.  
  973. /*
  974. #define MBDEBUG
  975. */
  976.  
  977. struct mbx *mbox[NUMMBX] ;
  978. int ax25mbox ;
  979.  
  980. static char mbbanner[] =
  981.     "[NET-$]\rWelcome to the %s TCP/IP Mailbox\r(C)hat, (S)end, (B)ye >\r" ;
  982. static char mbmenu[] = "(C)hat, (S)end, (B)ye >\r" ;
  983.  
  984. dombox(argc, argv)
  985. int argc ;
  986. char *argv[] ;
  987. {
  988.     if (argc < 2) {
  989.         domboxdisplay() ;
  990.         return 0 ;
  991.     }
  992.  
  993.     if (argv[1][0] == 'y' || (strcmp(argv[1],"on") == 0))
  994.         ax25mbox = 1 ;
  995.     else if (argv[1][0] == 'n' || (strcmp(argv[1],"off") == 0))
  996.         ax25mbox = 0 ;
  997.     else if (argv[1][0] == '?')
  998.         printf("ax25 mailbox is %s\n", ax25mbox ? "on" : "off") ;
  999.     else
  1000.         printf("usage: mbox [y|n|?]\n") ;
  1001.  
  1002.     return 0 ;
  1003. }
  1004.  
  1005. static domboxdisplay()
  1006. {
  1007.     int i ;
  1008.     struct mbx *m ;
  1009.     static char *states[] = {"NONE","CMD","SUBJ","DATA"} ;
  1010.     static char *mbtype[] = {"NONE","AX25 ","NET/ROM"} ;
  1011.     
  1012.     printf(" User     State    Type    &cb\n") ;
  1013.  
  1014.     for (i = 0 ; i < NUMMBX ; i++)
  1015.         if ((m = mbox[i]) != NULLMBX)
  1016.             printf("%10s %4s  %7s   %04x\n", m->name, states[m->state],
  1017.                     mbtype[m->type],
  1018.                     m->type == MBX_AX25 ? m->cb.ax25_cb : m->cb.nr4_cb) ;
  1019. }
  1020.  
  1021.     
  1022. static struct mbx *
  1023. newmbx()
  1024. {
  1025.     int i ;
  1026.     struct mbx *m ;
  1027.  
  1028.     for (i = 0 ; i < NUMMBX ; i++)
  1029.         if (mbox[i] == NULLMBX) {
  1030.             if ((m = mbox[i] = (struct mbx *)calloc(1,sizeof(struct mbx)))
  1031.                 == NULLMBX)
  1032.                 return NULLMBX ;
  1033.             m->mbnum = i ;
  1034.             return m ;
  1035.         }
  1036.  
  1037.     /* If we get here, there are no free mailbox sessions */
  1038.  
  1039.     return NULLMBX ;
  1040. }
  1041.  
  1042.  
  1043. /* Incoming mailbox session via ax.25 */
  1044.  
  1045. void
  1046. mbx_incom(axp,cnt)
  1047. register struct ax25_cb *axp ;
  1048. int16 cnt ;
  1049. {
  1050.     struct mbx *m ;
  1051.     struct mbuf *bp, *recv_ax25() ;
  1052.     char *cp ;
  1053.     extern char hostname[] ;
  1054.     void mbx_rx(), mbx_state() ;
  1055.     extern char *index() ;
  1056.     
  1057.     if ((m = newmbx()) == NULLMBX) {
  1058.         disc_ax25(axp) ;    /* no memory! */
  1059.         return ;
  1060.     }
  1061.  
  1062.     m->state = MBX_CMD ;    /* start in command state */
  1063.     m->type = MBX_AX25 ;    /* this is an ax.25 mailbox session */
  1064.     m->cb.ax25_cb = axp ;
  1065.  
  1066.     pax25(m->name,&axp->addr.dest) ;
  1067.     cp = index(m->name,'-') ;
  1068.     if (cp != NULLCHAR)            /* get rid of SSID */
  1069.         *cp = '\0' ;
  1070.  
  1071.     m->lp = m->line ;        /* point line pointer at buffer */
  1072.     axp->r_upcall = mbx_rx ;
  1073.     axp->s_upcall = mbx_state ;
  1074.     axp->user = (char *)m ;
  1075.  
  1076.     /* The following is necessary because we didn't know we had a */
  1077.     /* "real" ax25 connection until a data packet came in.  We    */
  1078.     /* can't be spitting banners out at every station who connects, */
  1079.     /* since they might be a net/rom or IP station.  Sorry.  */
  1080.     
  1081.     bp = recv_ax25(axp,cnt) ;        /* get the initial input */
  1082.     free_p(bp) ;                    /* and throw it away to avoid confusion */
  1083.  
  1084.     /* Now say hi */
  1085.     
  1086.     if ((bp = alloc_mbuf(strlen(hostname) + strlen(mbbanner) + 2)) == NULLBUF) {
  1087.         disc_ax25(axp) ; /* mbx_state will fix stuff up */
  1088.         return ;
  1089.     }
  1090.  
  1091.     *bp->data = PID_FIRST | PID_LAST | PID_NO_L3 ;    /* pid */
  1092.     (void)sprintf(bp->data+1,mbbanner,hostname) ;
  1093.     bp->cnt = strlen(bp->data+1) + 1 ;
  1094.  
  1095.     send_ax25(axp,bp) ;                    /* send greeting message and menu */
  1096. }
  1097.  
  1098. /* receive upcall for ax.25 */
  1099. /* mbx_rx collects lines, and calls mbx_line when they are complete. */
  1100. /* If the lines get too long, it arbitrarily breaks them. */
  1101.  
  1102. void mbx_rx(axp,cnt)
  1103. struct ax25_cb *axp ;
  1104. int16 cnt ;
  1105. {
  1106.     struct mbuf *bp, *recv_ax25() ;
  1107.     struct mbx *m ;
  1108.     char c ;
  1109.     int mbx_line() ;
  1110.     
  1111.     m = (struct mbx *)axp->user ;
  1112.     
  1113.     if ((bp = recv_ax25(axp,cnt)) == NULLBUF)
  1114.         return ;
  1115.  
  1116.     while (pullup(&bp,&c,1) == 1) {
  1117.         if (c == '\r') {
  1118.             *m->lp = '\0' ;            /* null terminate */
  1119.             if (mbx_line(m) == -1) {    /* call the line processor */
  1120.                 free_p(bp) ;        /* toss the rest */
  1121.                 break ;                /* get out - we're obsolete */
  1122.             }
  1123.             m->lp = m->line ;        /* reset the pointer */
  1124.         }
  1125.         else if ((m->lp - m->line) == (MBXLINE - 1)) {
  1126.             *m->lp++ = c ;
  1127.             *m->lp = '\0' ;
  1128.             if (mbx_line(m) == -1) {
  1129.                 free_p(bp) ;
  1130.                 break ;
  1131.             }
  1132.             m->lp = m->line ;
  1133.         }
  1134.         else
  1135.             *m->lp++ = c ;
  1136.     }
  1137. }
  1138.  
  1139. /* state upcall for ax.25 */
  1140.  
  1141. void mbx_state(axp,old,new)
  1142. struct ax25_cb *axp ;
  1143. int old, new ;
  1144. {
  1145.     struct mbx *m ;
  1146.     void free_mbx() ;
  1147.     
  1148.     m = (struct mbx *)axp->user ;
  1149.  
  1150.     /* dummy for now ... */
  1151.     if (new == DISCONNECTED) {
  1152.         axp->user = NULLCHAR ;
  1153.         free_mbx(m) ;
  1154.     }
  1155. }
  1156.  
  1157.  
  1158. /* Incoming mailbox session via net/rom */
  1159.  
  1160. void
  1161. mbx_nr4incom(cb)
  1162. register struct nr4cb *cb ;
  1163. {
  1164.     struct mbx *m ;
  1165.     struct mbuf *bp ;
  1166.     char *cp ;
  1167.     extern char hostname[] ;
  1168.     void mbx_nr4rx(), mbx_nr4state() ;
  1169.     extern char *index() ;
  1170.     
  1171.     if ((m = newmbx()) == NULLMBX) {
  1172.         disc_nr4(cb) ;    /* no memory! */
  1173.         return ;
  1174.     }
  1175.  
  1176.     m->state = MBX_CMD ;    /* start in command state */
  1177.     m->type = MBX_NETROM ;    /* mailbox session type is net/rom */
  1178.     m->cb.nr4_cb = cb ;
  1179.  
  1180.     pax25(m->name,&cb->user) ;
  1181.     cp = index(m->name,'-') ;
  1182.     if (cp != NULLCHAR)            /* get rid of SSID */
  1183.         *cp = '\0' ;
  1184.  
  1185.     m->lp = m->line ;        /* point line pointer at buffer */
  1186.     cb->r_upcall = mbx_nr4rx ;
  1187.     cb->s_upcall = mbx_nr4state ;
  1188.     cb->puser = (char *)m ;
  1189.  
  1190.     /* Say hi */
  1191.     
  1192.     if ((bp = alloc_mbuf(strlen(hostname) + strlen(mbbanner) + 1)) == NULLBUF) {
  1193.         disc_nr4(cb) ; /* mbx_nr4state will fix stuff up */
  1194.         return ;
  1195.     }
  1196.  
  1197.     (void)sprintf(bp->data,mbbanner,hostname) ;
  1198.     bp->cnt = strlen(bp->data) ;
  1199.  
  1200.     send_nr4(cb,bp) ;                    /* send greeting message and menu */
  1201. }
  1202.  
  1203. /* receive upcall for net/rom */
  1204. /* mbx_nr4rx collects lines, and calls mbx_line when they are complete. */
  1205. /* If the lines get too long, it arbitrarily breaks them. */
  1206.  
  1207. void mbx_nr4rx(cb,cnt)
  1208. struct nr4cb *cb ;
  1209. int16 cnt ;
  1210. {
  1211.     struct mbuf *bp ;
  1212.     struct mbx *m ;
  1213.     char c ;
  1214.     int mbx_line() ;
  1215.     
  1216.     m = (struct mbx *)cb->puser ;
  1217.     
  1218.     if ((bp = recv_nr4(cb,cnt)) == NULLBUF)
  1219.         return ;
  1220.  
  1221.     while (pullup(&bp,&c,1) == 1) {
  1222.         if (c == '\r') {
  1223.             *m->lp = '\0' ;            /* null terminate */
  1224.             if (mbx_line(m) == -1) {    /* call the line processor */
  1225.                 free_p(bp) ;        /* toss the rest */
  1226.                 break ;                /* get out - we're obsolete */
  1227.             }
  1228.             m->lp = m->line ;        /* reset the pointer */
  1229.         }
  1230.         else if ((m->lp - m->line) == (MBXLINE - 1)) {
  1231.             *m->lp++ = c ;
  1232.             *m->lp = '\0' ;
  1233.             if (mbx_line(m) == -1) {
  1234.                 free_p(bp) ;
  1235.                 break ;
  1236.             }
  1237.             m->lp = m->line ;
  1238.         }
  1239.         else
  1240.             *m->lp++ = c ;
  1241.     }
  1242. }
  1243.  
  1244. /* state upcall for net/rom */
  1245.  
  1246. void mbx_nr4state(cb,old,new)
  1247. struct nr4cb *cb ;
  1248. int old, new ;
  1249. {
  1250.     struct mbx *m ;
  1251.     void free_mbx() ;
  1252.     
  1253.     m = (struct mbx *)cb->puser ;
  1254.  
  1255.     if (new == NR4STDISC) {
  1256.         cb->puser = NULLCHAR ;
  1257.         free_mbx(m) ;
  1258.     }
  1259. }
  1260.  
  1261. static void
  1262. free_mbx(m)
  1263. struct mbx *m ;
  1264. {
  1265.     if (m->to != NULLCHAR)
  1266.         free(m->to) ;
  1267.  
  1268.  
  1269.     if (m->tofrom != NULLCHAR)
  1270.         free(m->tofrom) ;
  1271.  
  1272.     if (m->tomsgid != NULLCHAR)
  1273.         free(m->tomsgid) ;
  1274.         
  1275.     if (m->tfile != NULLFILE)
  1276.         fclose(m->tfile) ;
  1277.  
  1278.     mbox[m->mbnum] = NULLMBX ;
  1279.     
  1280.     free(m) ;
  1281. }
  1282.  
  1283.  
  1284. static 
  1285. mbx_line(m)
  1286. struct mbx *m ;
  1287. {
  1288.     void ax_session(), nr4_session(), mbx_disc() ;
  1289.     char *host ;
  1290.     extern char hostname[] ;
  1291.     char fullfrom[80] ;
  1292.     
  1293.     if (m->state == MBX_CMD) {
  1294.         switch (tolower(m->line[0])) {
  1295.             case 'b':    /* bye - bye */
  1296.                 mbx_disc(m) ;
  1297.                 return -1 ;    /* tell line processor to quit */
  1298.                 break ;
  1299.             case 'c':    /* chat */
  1300.                 switch (m->type) {
  1301.                   case MBX_AX25:
  1302.                     m->cb.ax25_cb->user = NULLCHAR ;
  1303.                     ax_session(m->cb.ax25_cb,0) ;    /* make it a chat session */
  1304.                     break ;
  1305.                   case MBX_NETROM:
  1306.                     m->cb.nr4_cb->puser = NULLCHAR ;
  1307.                     nr4_session(m->cb.nr4_cb) ;
  1308.                     break ;
  1309.                 }
  1310.                 free_mbx(m) ;
  1311.                 return -1 ;
  1312.                 break ;
  1313.             case 's': {
  1314.                 int badsubj = 0 ;
  1315.  
  1316.                 /* Get S-command type (B,P,T, etc.) */
  1317.                 
  1318.                 if (m->line[1] == '\0')
  1319.                     m->stype = ' ' ;
  1320.                 else
  1321.                     m->stype = toupper(m->line[1]) ;
  1322.                     
  1323.                 if (mbx_to(m) == -1) {
  1324.                     if (m->sid & MBX_SID)
  1325.                         mbx_msg(m,"NO\r") ;
  1326.                     else {
  1327.                         mbx_msg(m,
  1328.                             "S command syntax error - format is:\r") ;
  1329.                         mbx_msg(m,
  1330.                           "  S name [@ host] [< from_addr] [$bulletin_id]\r") ;
  1331.                     }
  1332.                     badsubj++ ;
  1333.                 }
  1334.                 else if (validate_address(m->to) == 0)     {
  1335.                     if (m->sid & MBX_SID)
  1336.                         mbx_msg(m, "NO\r") ;
  1337.                     else
  1338.                         mbx_msg(m, "Bad user or host name\r") ;
  1339.                     free(m->to) ;
  1340.                     m->to = NULLCHAR ;
  1341.                     if (m->tofrom) {
  1342.                         free(m->tofrom) ;
  1343.                         m->tofrom = NULLCHAR ;
  1344.                     }
  1345.                     if (m->tomsgid) {
  1346.                         free(m->tomsgid) ;
  1347.                         m->tomsgid = NULLCHAR ;
  1348.                     }
  1349.                     badsubj++ ;
  1350.                 }
  1351.  
  1352.                 if (badsubj)
  1353.                     mbx_msg(m, (m->sid & MBX_SID) ? ">\r" : mbmenu) ;
  1354.                 else {
  1355.                     m->state = MBX_SUBJ ;
  1356.                     mbx_msg(m,    (m->sid & MBX_SID) ? "OK\r" : "Subject:\r") ;
  1357.                 }
  1358.                 break ;
  1359.             }
  1360.             case '[':    /* This is a BBS - say "OK", not "Subject:" */
  1361.               {
  1362.                 int len = strlen(m->line) ;
  1363.                 
  1364.                 if (m->line[len - 1] == ']') { /* must be an SID */
  1365.                     m->sid = MBX_SID ;
  1366.                     /* Now check to see if this is an RLI board. */
  1367.                     /* As usual, Hank does it a bit differently from */
  1368.                     /* the rest of the world. */
  1369.                     if (len >= 5)        /* [RLI] at a minimum */
  1370.                         if (strncmp(&m->line[1],"RLI",3) == 0)
  1371.                             m->sid |= MBX_SID_RLI ;
  1372.                     
  1373.                     mbx_msg(m,">\r") ;
  1374.                 }
  1375.               }
  1376.               break ;
  1377.             case 'f':
  1378.                 if (m->line[1] == '>' && (m->sid & MBX_SID)) {
  1379.                     /* RLI BBS' expect us to disconnect if we */
  1380.                     /* have no mail for them, which of course */
  1381.                     /* we don't, being rather haughty about our */
  1382.                     /* protocol superiority. */
  1383.                     if (m->sid & MBX_SID_RLI) {
  1384.                         mbx_disc(m) ;
  1385.                         return -1 ;
  1386.                     } else
  1387.                         mbx_msg(m,">\r") ;
  1388.                     break ;
  1389.                 }
  1390.                 /* Otherwise drop through to "huh?" */
  1391.             default:
  1392.                 mbx_msg(m,"Huh?\r") ;
  1393.                 mbx_msg(m, (m->sid & MBX_SID) ? ">\r" : mbmenu) ;
  1394.         }
  1395.     return 0 ;
  1396.     }
  1397.     else if (m->state == MBX_SUBJ) {
  1398.         if (mbx_data(m) == -1) {
  1399.             mbx_msg(m,"Can't create temp file for mail\r") ;
  1400.             mbx_msg(m, (m->sid & MBX_SID) ? ">\r" : mbmenu) ;
  1401.             free(m->to) ;
  1402.             m->to = NULLCHAR ;
  1403.             if (m->tofrom) {
  1404.                 free(m->tofrom) ;
  1405.                 m->tofrom = NULLCHAR ;
  1406.             }
  1407.             if (m->tomsgid) {
  1408.                 free(m->tomsgid) ;
  1409.                 m->tomsgid = NULLCHAR ;
  1410.             }
  1411.             m->state = MBX_CMD ;
  1412.             return 0 ;
  1413.         }
  1414.         m->state = MBX_DATA ;
  1415.         if ((m->sid & MBX_SID) == 0)
  1416.             mbx_msg(m,
  1417.               "Enter message.  Terminate with /EX or ^Z in first column:\r") ;
  1418.         return 0 ;
  1419.     }
  1420.     else if (m->state == MBX_DATA) {
  1421.         if (m->line[0] == 0x1a ||
  1422.             strcmp(m->line, "/ex") == 0 ||
  1423.             strcmp(m->line, "/EX") == 0) {
  1424.             if ((host = index(m->to,'@')) == NULLCHAR)
  1425.                 host = hostname ;        /* use our hostname */
  1426.             else
  1427.                 host++ ;                /* use the host part of address */
  1428.  
  1429.             /* make up full from name for work file */
  1430.             (void)sprintf(fullfrom,"%s@%s",m->name,hostname) ;
  1431.             
  1432.             fseek(m->tfile,0L,0) ;        /* reset to beginning */
  1433.             if (queuejob((void *)0,m->tfile,host,m->to,fullfrom) != 0)
  1434.                 mbx_msg(m,
  1435.                         "Couldn't queue message for delivery\r") ;
  1436.  
  1437.             free(m->to) ;
  1438.             m->to = NULLCHAR ;
  1439.             if (m->tofrom) {
  1440.                 free(m->tofrom) ;
  1441.                 m->tofrom = NULLCHAR ;
  1442.             }
  1443.             if (m->tomsgid) {
  1444.                 free(m->tomsgid) ;
  1445.                 m->tomsgid = NULLCHAR ;
  1446.             }
  1447.             fclose(m->tfile) ;
  1448.             m->tfile = NULLFILE ;
  1449.             m->state = MBX_CMD ;
  1450.             mbx_msg(m, (m->sid & MBX_SID) ? ">\r" : mbmenu) ;
  1451.             return 0 ;
  1452.         }
  1453.         /* not done yet! */
  1454.         fprintf(m->tfile,"%s\n",m->line) ;
  1455.         return 0 ;
  1456.     }
  1457. }
  1458.  
  1459. static
  1460. mbx_msg(m,msg)
  1461. struct mbx *m ;
  1462. char msg[] ;
  1463. {
  1464.     int len ;
  1465.     struct mbuf *bp ;
  1466.     struct ax25_cb *axp ;
  1467.     struct nr4cb *cb ;
  1468.  
  1469.     len = strlen(msg) ;
  1470.  
  1471.     switch (m->type) {
  1472.       case MBX_AX25:
  1473.         axp = m->cb.ax25_cb ;
  1474.             
  1475.         if ((bp = alloc_mbuf(len+1)) == NULLBUF) {
  1476.             disc_ax25(axp) ;
  1477.             return -1 ;
  1478.         }
  1479.  
  1480.         bp->cnt = len + 1 ;
  1481.     
  1482.         *bp->data = PID_FIRST | PID_LAST | PID_NO_L3 ;
  1483.     
  1484.         memcpy(bp->data+1, msg, len) ;
  1485.  
  1486.         send_ax25(axp,bp) ;
  1487.  
  1488.         break ;
  1489.  
  1490.       case MBX_NETROM:
  1491.         cb = m->cb.nr4_cb ;
  1492.  
  1493.         if ((bp = alloc_mbuf(len)) == NULLBUF) {
  1494.             disc_nr4(cb) ;
  1495.             return -1 ;
  1496.         }
  1497.  
  1498.         bp->cnt = len ;
  1499.  
  1500.         memcpy(bp->data, msg, len) ;
  1501.  
  1502.         send_nr4(cb, bp) ;
  1503.  
  1504.         break ;
  1505.     }
  1506.     return 0 ;
  1507. }
  1508.  
  1509.  
  1510. /* States for send line parser state machine */
  1511.  
  1512. #define        SKIP_CMD        1
  1513. #define        LOOK_FOR_USER    2
  1514. #define        IN_USER            3
  1515. #define        AFTER_USER        4
  1516. #define        LOOK_FOR_HOST    5
  1517. #define        IN_HOST            6
  1518. #define        AFTER_HOST        7
  1519. #define        LOOK_FOR_FROM    8
  1520. #define        IN_FROM            9
  1521. #define        AFTER_FROM        10
  1522. #define        LOOK_FOR_MSGID    11
  1523. #define        IN_MSGID        12
  1524. #define        FINAL_STATE        13
  1525. #define        ERROR_STATE        14
  1526.  
  1527. /* Prepare the addressee.  If the address is bad, return -1, otherwise
  1528.  * return 0
  1529.  */
  1530. static
  1531. mbx_to(m)
  1532. struct mbx *m ;
  1533. {
  1534.     register char *cp, *cp1 ;
  1535.     int state ;
  1536.     char *user, *host, *from, *msgid ;
  1537.     int userlen = 0, hostlen = 0, fromlen = 0, msgidlen = 0 ;
  1538.     
  1539.     cp = m->line ;
  1540.  
  1541.     for (state = SKIP_CMD ; state < FINAL_STATE ; cp++) {
  1542. #ifdef MBDEBUG
  1543.         printf("State is %d, char is %c\n", state, *cp) ;
  1544. #endif
  1545.         switch (state) {
  1546.             case SKIP_CMD:
  1547.                 if (*cp == '\0')
  1548.                     state = ERROR_STATE ;        /* no user */
  1549.                 else if (isspace(*cp))
  1550.                     state = LOOK_FOR_USER ;
  1551.                 break ;
  1552.             case LOOK_FOR_USER:
  1553.                 if (*cp == '\0' || *cp == '@' || *cp == '<' || *cp == '$')
  1554.                     state = ERROR_STATE ;        /* no user */
  1555.                 else if (!isspace(*cp)) {        /* found start of user */
  1556.                     user = cp ;                    /* point at start */
  1557.                     userlen++ ;                    /* start counting */
  1558.                     state = IN_USER ;
  1559.                 }
  1560.                 break ;
  1561.             case IN_USER:
  1562.                 switch (*cp) {
  1563.                     case '\0':                    /* found username only */
  1564.                         state = FINAL_STATE ;
  1565.                         break ;
  1566.                     case '@':
  1567.                         state = LOOK_FOR_HOST ;    /* hostname should follow */
  1568.                         break ;
  1569.                     case '<':
  1570.                         state = LOOK_FOR_FROM ;    /* from name should follow */
  1571.                         break ;
  1572.                     case '$':
  1573.                         state = LOOK_FOR_MSGID ; /* message id should follow */
  1574.                         break ;
  1575.                     default:
  1576.                         if (isspace(*cp))
  1577.                             state = AFTER_USER ;    /* white space */
  1578.                         else
  1579.                             userlen++ ;                /* part of username */
  1580.                 }
  1581.                 break ;
  1582.             case AFTER_USER:
  1583.                 switch (*cp) {
  1584.                     case '\0':
  1585.                         state = FINAL_STATE ;        /* found username only */
  1586.                         break ;
  1587.                     case '@':
  1588.                         state = LOOK_FOR_HOST ;        /* hostname follows */
  1589.                         break ;
  1590.                     case '<':
  1591.                         state = LOOK_FOR_FROM ;        /* fromname follows */
  1592.                         break ;
  1593.                     case '$':
  1594.                         state = LOOK_FOR_MSGID ;    /* message id follows */
  1595.                         break ;
  1596.                     default:
  1597.                         if (!isspace(*cp))
  1598.                             state = ERROR_STATE ;
  1599.                 }
  1600.                 break ;
  1601.             case LOOK_FOR_HOST:
  1602.                 switch (*cp) {
  1603.                     case '\0':                    /* user@? */
  1604.                     case '@':                    /* user@@ */
  1605.                     case '<':                    /* user@< */
  1606.                     case '$':                    /* user@$ */
  1607.                         state = ERROR_STATE ;
  1608.                         break ;
  1609.                     default:
  1610.                         if (!isspace(*cp)) {
  1611.                             host = cp ;
  1612.                             hostlen++ ;
  1613.                             state = IN_HOST ;
  1614.                         }
  1615.                 }
  1616.                 break ;
  1617.             case IN_HOST:
  1618.                 switch (*cp) {
  1619.                     case '\0':
  1620.                         state = FINAL_STATE ;        /* found user@host */
  1621.                         break ;
  1622.                     case '@':
  1623.                         state = ERROR_STATE ;        /* user@host@? */
  1624.                         break ;
  1625.                     case '<':
  1626.                         state = LOOK_FOR_FROM ;        /* fromname follows */
  1627.                         break ;
  1628.                     case '$':
  1629.                         state = LOOK_FOR_MSGID ;    /* message id follows */
  1630.                         break ;
  1631.                     default:
  1632.                         if (isspace(*cp))
  1633.                             state = AFTER_HOST ;
  1634.                         else
  1635.                             hostlen++ ;
  1636.                 }
  1637.                 break ;
  1638.             case AFTER_HOST:
  1639.                 switch (*cp) {
  1640.                     case '\0':
  1641.                         state = FINAL_STATE ;        /* user@host */
  1642.                         break ;
  1643.                     case '@':
  1644.                         state = ERROR_STATE ;        /* user@host @ */
  1645.                         break ;
  1646.                     case '<':
  1647.                         state = LOOK_FOR_FROM ;        /* user@host < */
  1648.                         break ;
  1649.                     case '$':
  1650.                         state = LOOK_FOR_MSGID ;    /* user@host $ */
  1651.                         break ;
  1652.                     default:
  1653.                         if (!isspace(*cp))
  1654.                             state = ERROR_STATE ;    /* user@host foo */
  1655.                 }
  1656.                 break ;
  1657.             case LOOK_FOR_FROM:
  1658.                 switch (*cp) {
  1659.                     case '\0':                    /* user@host <? */
  1660.                     case '@':                    /* user@host <@ */
  1661.                     case '<':                    /* user@host << */
  1662.                     case '$':                    /* user@host <$ */
  1663.                         state = ERROR_STATE ;
  1664.                         break ;
  1665.                     default:
  1666.                         if (!isspace(*cp)) {
  1667.                             from = cp ;
  1668.                             fromlen++ ;
  1669.                             state = IN_FROM ;
  1670.                         }
  1671.                 }
  1672.                 break ;
  1673.             case IN_FROM:
  1674.                 switch (*cp) {
  1675.                     case '\0':
  1676.                         state = FINAL_STATE ;        /* user@host <foo */
  1677.                         break ;
  1678.                     case '<':
  1679.                         state = ERROR_STATE ;        /* user@host <foo< */
  1680.                         break ;
  1681.                     case '$':
  1682.                         state = LOOK_FOR_MSGID ;    /* message id follows */
  1683.                         break ;
  1684.                     default:
  1685.                         if (isspace(*cp))
  1686.                             state = AFTER_FROM ;
  1687.                         else
  1688.                             fromlen++ ;
  1689.                 }
  1690.                 break ;
  1691.             case AFTER_FROM:
  1692.                 switch (*cp) {
  1693.                     case '\0':
  1694.                         state = FINAL_STATE ;        /* user@host <foo */
  1695.                         break ;
  1696.                     case '@':                        /* user@host <foo @ */
  1697.                     case '<':                        /* user@host <foo < */
  1698.                         state = ERROR_STATE ;
  1699.                         break ;
  1700.                     case '$':
  1701.                         state = LOOK_FOR_MSGID ;    /* user@host <foo $ */
  1702.                         break ;
  1703.                     default:
  1704.                         if (!isspace(*cp))
  1705.                             state = ERROR_STATE ;    /* user@host foo */
  1706.                 }
  1707.                 break ;
  1708.             case LOOK_FOR_MSGID:
  1709.                 if (*cp == '\0')
  1710.                     state = ERROR_STATE ;            /* msgid = $? */
  1711.                 else if (isspace(*cp))
  1712.                     state = ERROR_STATE ;            /* user@host <foo $ bar */
  1713.                 else {
  1714.                     msgid = cp ;
  1715.                     msgidlen++ ;
  1716.                     state = IN_MSGID ;
  1717.                 }
  1718.                 break ;
  1719.             case IN_MSGID:
  1720.                 if (*cp == '\0')
  1721.                     state = FINAL_STATE ;
  1722.                 else if (isspace(*cp))
  1723.                     state = FINAL_STATE ;
  1724.                 else
  1725.                     msgidlen++ ;
  1726.                 break ;
  1727.             default:
  1728.                 /* what are we doing in this state? */
  1729.                 state = ERROR_STATE ;
  1730.         }
  1731.     }
  1732.  
  1733.     if (state == ERROR_STATE)
  1734.         return -1 ;        /* syntax error */
  1735.  
  1736.     if ((m->to = malloc(userlen + hostlen + 2)) == NULLCHAR)
  1737.         return -1 ;        /* no room for to address */
  1738.  
  1739.     strncpy(m->to, user, userlen) ;
  1740.     m->to[userlen] = '\0' ;
  1741.     
  1742.     if (hostlen) {
  1743.         m->to[userlen] = '@' ;
  1744.         strncpy(m->to + userlen + 1, host, hostlen) ;
  1745.         m->to[userlen + hostlen + 1] = '\0' ;
  1746.     }
  1747.  
  1748.     if (fromlen) {
  1749.         if ((m->tofrom = malloc(fromlen + 1)) == NULLCHAR) {
  1750.             free(m->to) ;
  1751.             m->to = NULLCHAR ;
  1752.             return -1 ;
  1753.         }
  1754.         strncpy(m->tofrom, from, fromlen) ;
  1755.         m->tofrom[fromlen] = '\0' ;
  1756.     }
  1757.  
  1758.     if (msgidlen) {
  1759.         if ((m->tomsgid = malloc(msgidlen + 1)) == NULLCHAR) {
  1760.             free(m->to) ;
  1761.             m->to = NULLCHAR ;
  1762.             if (fromlen) {
  1763.                 free(m->tofrom) ;
  1764.                 m->tofrom = NULLCHAR ;
  1765.             }
  1766.             return -1 ;
  1767.         }
  1768.         strncpy(m->tomsgid, msgid, msgidlen) ;
  1769.         m->tomsgid[msgidlen] = '\0' ;
  1770.     }
  1771.     
  1772.     return 0 ;
  1773. }
  1774.  
  1775. /* This opens the data file and writes the mail header into it.
  1776.  * Returns 0 if OK, and -1 if not.
  1777.  */
  1778.  
  1779. static
  1780. mbx_data(m)
  1781. struct mbx *m ;
  1782. {
  1783.     time_t t, time() ;
  1784.     char *ptime() ;
  1785.     extern char hostname[] ;
  1786.     extern FILE *tmpfile();
  1787.     extern long get_msgid() ;
  1788.     
  1789.     if ((m->tfile = tmpfile()) == NULLFILE)
  1790.         return -1 ;
  1791.  
  1792.     time(&t) ;
  1793.     fprintf(m->tfile,"Date: %s",ptime(&t)) ;
  1794.     if (m->tomsgid)
  1795.         fprintf(m->tfile, "Message-Id: <%s@%s>\n", m->tomsgid, hostname) ;
  1796.     else
  1797.         fprintf(m->tfile,"Message-Id: <%ld@%s>\n",get_msgid(),hostname) ;
  1798.     fprintf(m->tfile,"From: %s%%%s.bbs@%s\n",
  1799.             m->tofrom ? m->tofrom : m->name, m->name, hostname) ;
  1800.     fprintf(m->tfile,"To: %s\n",m->to) ;
  1801.     fprintf(m->tfile,"Subject: %s\n",m->line) ;
  1802.     if (m->stype != ' ')
  1803.         fprintf(m->tfile,"X-BBS-Msg-Type: %c\n", m->stype) ;
  1804.     fprintf(m->tfile,"\n") ;
  1805.     
  1806.     return 0 ;
  1807. }
  1808.  
  1809. /* Shut down the mailbox communications connection */
  1810.  
  1811. static void
  1812. mbx_disc(m)
  1813. struct mbx *m ;
  1814. {
  1815.     switch (m->type) {
  1816.       case MBX_AX25:
  1817.         disc_ax25(m->cb.ax25_cb) ;
  1818.         break ;
  1819.       case MBX_NETROM:
  1820.           disc_nr4(m->cb.nr4_cb) ;
  1821.         break ;
  1822.     }
  1823. }
  1824. #endif /* XOBBS */
  1825.